package megadrum.gui;

import java.lang.reflect.Method;
import megadrum.*;
import megadrum.mididata.Converter;
import javax.swing.JSpinner;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

public class MiscPanel extends javax.swing.JPanel implements ChangeListener{

    public MiscPanel(MegadrumConfigTool mct) {
        parent = mct;
        initComponents();
        initComponents2();
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        javax.swing.JLabel jLabel16 = new javax.swing.JLabel();
        noteOffDelay = new javax.swing.JSpinner();
        javax.swing.JLabel jLabel17 = new javax.swing.JLabel();
        latency = new javax.swing.JSpinner();
        jPanel1 = new javax.swing.JPanel();
        check_quickAccess = new javax.swing.JCheckBox();
        check_bigVUMeter = new javax.swing.JCheckBox();
        check_allGainsLow = new javax.swing.JCheckBox();
        check_altFalseTrig = new javax.swing.JCheckBox();
        midiUSB = new javax.swing.JRadioButton();
        midiSerial = new javax.swing.JRadioButton();

        setBorder(javax.swing.BorderFactory.createTitledBorder("Miscellaneous options"));

        jLabel16.setText("Note Off Delay");
        jLabel16.setToolTipText("<html>&nbsp;Time in milliseconds to send the&nbsp;<br> &nbsp;Note Off for each Note On event&nbsp;");

        noteOffDelay.setToolTipText("<html>&nbsp;Time in milliseconds to send the&nbsp;<br>\n&nbsp;Note Off for each Note On event&nbsp;");

        jLabel17.setText("Latency");
        jLabel17.setToolTipText("<html>&nbsp; Sets the latency time. 1 unit equals 100us&nbsp;<br>&nbsp; The default value is 40 (4 millinseconds)&nbsp;");

        latency.setToolTipText("<html>&nbsp;\nSets the latency time. 1 unit equals 100us&nbsp;<br>&nbsp;\nThe default value is 40 (4 millinseconds)&nbsp;");

        jPanel1.setLayout(new java.awt.GridLayout(3, 2, 5, 0));

        check_quickAccess.setText("Quick Access");
        check_quickAccess.setToolTipText("<html>&nbsp;\nIf you enable this, you can jump to any pad config&nbsp;<br>&nbsp;\nin Megadrum menu, by hitting the pad while you&nbsp;<br>&nbsp;\nkeep hihat pedal pressed&nbsp;");
        check_quickAccess.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        check_quickAccess.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        check_quickAccess.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        check_quickAccess.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jPanel1.add(check_quickAccess);

        check_bigVUMeter.setText("Big VU meter");
        check_bigVUMeter.setToolTipText("<html>&nbsp;\nEnable to see 2 big VU meters on LCD screen&nbsp;<br>&nbsp;\n(one for hihat pedal and one for all pads).&nbsp;<br>&nbsp;\nDisable to see VU meters for hihat pedal and&nbsp;<br>&nbsp;\nfor every single input.&nbsp;");
        check_bigVUMeter.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        check_bigVUMeter.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        check_bigVUMeter.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        check_bigVUMeter.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jPanel1.add(check_bigVUMeter);

        check_allGainsLow.setText("All Gains Low");
        check_allGainsLow.setToolTipText("<html>&nbsp;Megadrum will disable the Gain multiplier for&nbsp;<br>&nbsp;all inputs. This is useful if you have \"hot\" pads&nbsp;");
        check_allGainsLow.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        check_allGainsLow.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        check_allGainsLow.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        check_allGainsLow.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jPanel1.add(check_allGainsLow);

        check_altFalseTrig.setText("Alt False Trig");
        check_altFalseTrig.setToolTipText("Enable to use an alternative false triggering suppression algorithm");
        check_altFalseTrig.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        check_altFalseTrig.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        check_altFalseTrig.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        check_altFalseTrig.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jPanel1.add(check_altFalseTrig);

        midiUSB.setText("Speed:38400");
        midiUSB.setEnabled(false);
        midiUSB.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        midiUSB.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        jPanel1.add(midiUSB);

        midiSerial.setSelected(true);
        midiSerial.setText("Speed:31250");
        midiSerial.setEnabled(false);
        midiSerial.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        midiSerial.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        jPanel1.add(midiSerial);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel17)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, jLabel16))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                            .add(noteOffDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
                            .add(latency, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 85, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 169, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, jLabel16, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, noteOffDelay, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 20, Short.MAX_VALUE))
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(latency, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 20, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel17, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 21, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 81, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    public void initComponents2() {
        //add radio buttons to group
        buttonGroup1.add(midiUSB);
        buttonGroup1.add(midiSerial);

        //set data models
        noteOffDelay.setModel(new CustomSpinnerIntModel(200, 100, 2000, 10));
        latency.setModel(new CustomSpinnerIntModel(40, 10, 100, 1));

        //set a white background for all fields
        ((JSpinner.DefaultEditor) noteOffDelay.getEditor()).getTextField().setBackground(java.awt.Color.WHITE);
        ((JSpinner.DefaultEditor) noteOffDelay.getEditor()).getTextField().setForeground(java.awt.Color.BLACK);
        ((JSpinner.DefaultEditor) latency.getEditor()).getTextField().setBackground(java.awt.Color.WHITE);
        ((JSpinner.DefaultEditor) latency.getEditor()).getTextField().setForeground(java.awt.Color.BLACK);

        //add change listeners
        noteOffDelay.addChangeListener(this);
        latency.addChangeListener(this);
        midiUSB.addChangeListener(this); //only need to add listener to one checkbox of the group
        check_allGainsLow.addChangeListener(this);
        check_altFalseTrig.addChangeListener(this);
        check_bigVUMeter.addChangeListener(this);
        check_quickAccess.addChangeListener(this);

        //add popup slider to fields with high value ranges
        new PopupSlider(noteOffDelay);
        new PopupSlider(latency);
    }
/*
    public void convertSysexToData(byte sysex[]) {

        try {
            Method m = megadrum.gui.HihatPanel.class.getMethod("convertSysexToDataOld", new Class[]{byte[].class});
            m.invoke(this, sysex);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public byte[] convertDataToSysex() {
        byte[] b = new byte[0];
        try {
            Method m = megadrum.gui.HihatPanel.class.getMethod("convertDataToSysexOld", null);
            b = (byte[]) m.invoke(this, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return b;
    }
*/
    //method for converting received sysex data to values and set them in the GUI fields

    public void convertSysexToData(byte sysex[]) {
        if (sysex.length == Common.LENGTH_MISC) { //misc config sysex must be 7 bytes long
            tempDisableStateChangedEvents = true; //to avoid stateChanged method to be executed
            ((CustomSpinnerModel) noteOffDelay.getModel()).setIntValue(10 * Converter.twoBytesToOneInt(sysex[4], sysex[5]));
            ((CustomSpinnerModel) latency.getModel()).setIntValue(Converter.twoBytesToOneInt(sysex[6], sysex[7]));
            check_quickAccess.setSelected(Converter.getBooleanFromBitInByte(sysex[9], 3));
            check_bigVUMeter.setSelected(Converter.getBooleanFromBitInByte(sysex[9], 2));
            check_allGainsLow.setSelected(Converter.getBooleanFromBitInByte(sysex[9], 0));
            boolean midiSpeed = Converter.getBooleanFromBitInByte(sysex[8],0); //MIDI speed (false: serial, true: USB)
            midiUSB.setSelected(midiSpeed);
            midiSerial.setSelected(!midiSpeed);
            check_altFalseTrig.setSelected( Converter.getBooleanFromBitInByte(sysex[8],1) ); //AltFalseTrSupp
            tempDisableStateChangedEvents = false; //enable again stateChanged events
        }
    }

    //method for converting values in the GUI to a sysex message ready to be sent

    public byte[] convertDataToSysex() {
        byte[] sysex = new byte[Common.LENGTH_MISC];
        sysex[0] = Common.SYSEX_BEGIN;
        sysex[1] = Common.SYSEX_ID;
        sysex[2] = (byte) parent.getChainID();
        sysex[3] = Common.TYPE_MISC;
        sysex[4] = Converter.intToTwoBytes(((CustomSpinnerModel) noteOffDelay.getModel()).getIntValue() / 10)[0]; //convert int to byte, and then to 2 bytes
        sysex[5] = Converter.intToTwoBytes(((CustomSpinnerModel) noteOffDelay.getModel()).getIntValue() / 10)[1];
        sysex[6] = Converter.intToTwoBytes(((CustomSpinnerModel) latency.getModel()).getIntValue())[0]; //convert int to byte, and then to 2 bytes
        sysex[7] = Converter.intToTwoBytes(((CustomSpinnerModel) latency.getModel()).getIntValue())[1];
        sysex[8] = Converter.bitsToNibble(
                false,
                false,
                check_altFalseTrig.isSelected(),
                midiUSB.isSelected());
        sysex[9] = Converter.bitsToNibble(
                check_quickAccess.isSelected(),
                check_bigVUMeter.isSelected(),
                false,
                check_allGainsLow.isSelected());
        sysex[10] = (byte) 0x00;
        sysex[11] = (byte) 0x00;
        sysex[12] = Common.SYSEX_END;
        return sysex;
    }

    public void stateChanged(ChangeEvent e) {
        if (!tempDisableStateChangedEvents) {
            //Some parameter has been changed, if Live Editing is enabled, schedule a sending
            if(parent.getLiveEditingEnabled()){
                parent.scheduleSending(Common.MISC_EVENT);
            }
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JCheckBox check_allGainsLow;
    private javax.swing.JCheckBox check_altFalseTrig;
    private javax.swing.JCheckBox check_bigVUMeter;
    private javax.swing.JCheckBox check_quickAccess;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JSpinner latency;
    private javax.swing.JRadioButton midiSerial;
    private javax.swing.JRadioButton midiUSB;
    private javax.swing.JSpinner noteOffDelay;
    // End of variables declaration//GEN-END:variables
    private MegadrumConfigTool parent;
    private boolean tempDisableStateChangedEvents = false;
}
